
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.Xml;
using System.Diagnostics;


using Swaf;
using Swaf.BizObj;
using Swaf.Container;

namespace Swaf.BizObj.xml
{
	[Serializable]
	public class XmlDotNetNode : INameAddressSupport
	{
		protected IBizObjField m_field;
		protected IXmlNodeParent m_parent;

		public XmlDotNetNode(IBizObjField field, IXmlNodeParent parent)
		{
			m_field = field;
			m_parent = parent;
		}

		#region INameAddressSupport Members

		public virtual bool isGetOnly {get{return false;}}

		public virtual void put(string nameAddress, object val)
		{
			put(nameAddress, val, null);
		}

		public virtual void put(string nameAddress, object val, object extraInfo)
		{
			XmlElement el = m_parent.getChildElement(m_field.Name, true);
			if(el != null)
			{
				XmlAttribute attr = el.GetAttributeNode(m_field.Name);
				XmlElement childNode = null;
				if (attr == null)
				{
					//childNode = (XmlElement)el.SelectSingleNode(m_field.Name);
					childNode = Cmn.findChildWithName(el, m_field.Name);
					//if (childNode == null)
					//{
					//	attr = el.SetAttributeNode(m_field.Name, null);
					//	attr.Value = val.ToString();
					//	return;
					//}
				}
				if (attr != null)
				{
					if(val == null)
						el.RemoveChild(attr);
					else
						attr.Value = val.ToString();
				}
				else if (childNode != null)
				{
					if(val == null)
						el.RemoveChild(childNode);
					else
						childNode.Value = val.ToString();
				}
			}
		}
	
		public object get(string nameAddress, object oneArg)
		{
			return this.get(nameAddress, new object[]{oneArg});
		}

		public object get(string nameAddress)
		{
			return this.get(nameAddress, new object[]{});
		}

		public virtual object get(string nameAddress, params object[] infoArgs)
		{
			XmlElement el = m_parent.getChildElement(m_field.Name, false);
			if(el != null)
			{
				XmlAttribute attr = el.GetAttributeNode(m_field.Name);
				XmlElement childNode = null;
				if (attr == null)
				{
					//childNode = (XmlElement)el.SelectSingleNode(m_field.Name);
					childNode = Cmn.findChildWithName(el, m_field.Name);
					//if (childNode == null)
					//{
					//	attr = el.SetAttributeNode(m_field.Name, null);
					//	attr.Value = m_field.SampleValue == null?null:m_field.SampleValue.ToString();
					//}
				}
				
				if (attr != null)
				{
					try
					{
						return Serialization.deserialize(m_field.SampleValue.GetType().FullName, attr.Value);
						//return Cmn.callMethod(m_field.SampleValue, 
						//	"Parse", new System.Type[]{typeof(string)}, new object[]{attr.Value});
					}
					catch (Exception)
					{
						return attr.Value;
					}				
				}
				else if (childNode != null)
					return childNode.Value;
			}
				
			return m_field.SampleValue;
		}


		public virtual XmlSerializationSupport SerializationSupport
		{get{return XmlSerializationSupport.AsAttribute;}}

		public virtual string Xml
		{get{return null;}}

		public virtual string getXml(string options)
		{return null;}

		public virtual bool containsField(String nameAddress)
		{return false;}

		#endregion
		public IEnumerator GetEnumerator() { return null; }

		protected XmlElement getChildElementWithName(string name, XmlElement node)
		{
			//Performance of SelectSingleNode seems to blow away using GetElementsByTagName method
			//return (XmlElement)node.SelectSingleNode(name);
			return Cmn.findChildWithName(node, name);
			//XmlNodeList l = node.GetElementsByTagName(name);
			//if(l != null && l.Count > 0)
			//	return (XmlElement)l.Item(0);
			//return null;
		}

	}
/*
	public class XmlBizObjFieldNode : XmlContainerNode
	{
		public XmlBizObjFieldNode(object extraInfo)
		:base(extraInfo.ToString())
		{ }

		protected override object getWithNode(string name, XmlBaseBusinessObject parent, XmlElement node)
		{
			XmlAttribute attr = node.GetAttributeNode(name);
			XmlElement childNode = null;
			if (attr == null)
			{
				childNode = (XmlElement)node.SelectSingleNode(name);
				if (childNode == null)
				{
					attr = node.SetAttributeNode(name, null);
					attr.Value = parent.m_type.getField(name, true).SampleValue.ToString();
				}
			}
			
			if (attr != null)
			{
				try
				{
					return Cmn.callMethod(parent.m_type.getField(name, true).SampleValue, 
						"Parse", new System.Type[]{typeof(string)}, new object[]{attr.Value});
				}
				catch (Exception)
				{
					return attr.Value;
				}				
			}
			else if (childNode != null)
				return childNode.Value;
			
			return null;
		}
		
		protected override void putWithNode(string name, XmlBaseBusinessObject parent, XmlElement node, object val)
		{
			XmlAttribute attr = node.GetAttributeNode(name);
			XmlElement childNode = null;
			if (attr == null)
			{
				childNode = (XmlElement)node.SelectSingleNode(name);
				if (childNode == null)
				{
					attr = node.SetAttributeNode(name, null);
					attr.Value = val.ToString();
					return;
				}
			}
			if (attr != null)
			{
				attr.Value = val.ToString();
			}
			else if (childNode != null)
			{
				childNode.Value = val.ToString();
			}
		}
	}

		
	
	public class BizObjExpression : XmlContainerNode
	{
		//This class is only for fields that will be BizObjs
		protected IBizObjDefinition m_fieldType;

		public BizObjExpression(object extraInfo)
			:base(extraInfo.ToString())
		{	}

		protected override object getWithNode(string name, XmlBaseBusinessObject parent, XmlElement node)
		{
			IBizObj bizObj = null;

			XmlElement childNode = getChildElementWithName(name, node);
			if (childNode == null)
				childNode = (XmlElement)node.AppendChild(node.OwnerDocument.CreateElement(name));
			if (childNode != null)
			{
				try
				{
					if(m_fieldType == null)
					{
						IBizObjField myField = (IBizObjField)parent.type.Fields[name];
						if(myField.BizType == BizFieldType.BizObj)
							m_fieldType = ((IBizObj)myField.SampleValue).type;
					}
					bizObj = new XmlBusinessObject(m_fieldType, childNode);
				}
				catch (Exception e)
				{
					Application.currentApp.Log.println(e.Message);
				}
			}
			return bizObj;
		}
	}
		
	public class BizObjListExpression : XmlContainerNode
	{
		protected string m_listObjType;
		protected IBizObjDefinition m_fieldType;
		protected BizObjManager m_bizObjMgr;

		public BizObjListExpression(string fldName, string listObjType)
			:base(fldName)
		{
			BizObjManager m_bizObjMgr = (BizObjManager)Application.currentApp.bizObjMgr;
			m_listObjType = listObjType;
			m_fieldType = m_bizObjMgr.getBizObjInfo(m_listObjType);
			Debug.Assert(m_fieldType != null, "Unable to get field type " + listObjType);
		}

		protected override object getWithNode(string name, XmlBaseBusinessObject parent, XmlElement node)
		{
			IBizObjCursor list = null;
			try
			{
				XmlElement listBaseEl = getChildElementWithName(name, node);
				if (listBaseEl == null)
					listBaseEl = (XmlElement)node.AppendChild(node.OwnerDocument.CreateElement(name));
				list = new XmlBusinessObjectList(m_fieldType, new ListState(listBaseEl, m_fieldType.Name, true));
			}
			catch (Exception e)
			{
				Application.currentApp.Log.println(e.Message);
			}
			return list;
		}
	}
	*/
	

}